use serde::{Deserialize, Serialize};
use thiserror::Error;

/// Tauri 命令错误类型
#[derive(Error, Debug, Clone, Serialize, Deserialize)]
pub enum TauriCommandError {
    #[error("文件系统错误: {message}")]
    FileSystem { message: String },
    
    #[error("CodeGraph 错误: {message}")]
    CodeGraph { message: String },
    
    #[error("LSP 错误: {message}")]
    Lsp { message: String },
    
    #[error("解析错误: {message}")]
    Parse { message: String },
    
    #[error("IO 错误: {message}")]
    Io { message: String },
    
    #[error("序列化错误: {message}")]
    Serialization { message: String },
    
    #[error("验证错误: {message}")]
    Validation { message: String },
    
    #[error("超时错误: {message}")]
    Timeout { message: String },
    
    #[error("权限错误: {message}")]
    Permission { message: String },
    
    #[error("未知错误: {message}")]
    Unknown { message: String },

    #[error("配置错误: {message}")]
    Config { message: String },
}

impl TauriCommandError {
    pub fn file_system(message: impl Into<String>) -> Self {
        Self::FileSystem { message: message.into() }
    }
    
    pub fn codegraph(message: impl Into<String>) -> Self {
        Self::CodeGraph { message: message.into() }
    }
    
    pub fn lsp(message: impl Into<String>) -> Self {
        Self::Lsp { message: message.into() }
    }
    
    pub fn parse(message: impl Into<String>) -> Self {
        Self::Parse { message: message.into() }
    }
    
    pub fn io(message: impl Into<String>) -> Self {
        Self::Io { message: message.into() }
    }
    
    pub fn serialization(message: impl Into<String>) -> Self {
        Self::Serialization { message: message.into() }
    }
    
    pub fn validation(message: impl Into<String>) -> Self {
        Self::Validation { message: message.into() }
    }

    pub fn service_initialization(message: impl Into<String>) -> Self {
        Self::Io {
            message: format!("Service initialization failed: {}", message.into())
        }
    }

    pub fn service_not_initialized(message: impl Into<String>) -> Self {
        Self::Io {
            message: format!("Service not initialized: {}", message.into())
        }
    }
    
    pub fn timeout(message: impl Into<String>) -> Self {
        Self::Timeout { message: message.into() }
    }
    
    pub fn permission(message: impl Into<String>) -> Self {
        Self::Permission { message: message.into() }
    }
    
    pub fn unknown(message: impl Into<String>) -> Self {
        Self::Unknown { message: message.into() }
    }

    pub fn config(message: impl Into<String>) -> Self {
        Self::Config { message: message.into() }
    }
}

/// AppError 类型别名，用于配置管理
pub type AppError = TauriCommandError;

// 从标准库错误类型转换
impl From<std::io::Error> for TauriCommandError {
    fn from(err: std::io::Error) -> Self {
        Self::io(err.to_string())
    }
}

impl From<serde_json::Error> for TauriCommandError {
    fn from(err: serde_json::Error) -> Self {
        Self::serialization(err.to_string())
    }
}

// 暂时注释，等待 codegraph_core 修复
// impl From<codegraph_core::CodeGraphError> for TauriCommandError {
//     fn from(err: codegraph_core::CodeGraphError) -> Self {
//         Self::codegraph(err.to_string())
//     }
// }

impl From<anyhow::Error> for TauriCommandError {
    fn from(err: anyhow::Error) -> Self {
        Self::unknown(err.to_string())
    }
}

// 转换为 Tauri 错误
impl From<TauriCommandError> for tauri::Error {
    fn from(err: TauriCommandError) -> Self {
        tauri::Error::Anyhow(anyhow::anyhow!(err.to_string()))
    }
}

/// Tauri 命令结果类型
pub type TauriResult<T> = Result<T, TauriCommandError>;

/// 标准化的命令响应结构
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CommandResponse<T> {
    pub success: bool,
    pub data: Option<T>,
    pub error: Option<String>,
    pub timestamp: chrono::DateTime<chrono::Utc>,
}

impl<T> CommandResponse<T> {
    pub fn success(data: T) -> Self {
        Self {
            success: true,
            data: Some(data),
            error: None,
            timestamp: chrono::Utc::now(),
        }
    }
    
    pub fn error(error: impl Into<String>) -> Self {
        Self {
            success: false,
            data: None,
            error: Some(error.into()),
            timestamp: chrono::Utc::now(),
        }
    }
}

/// 进度报告结构
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProgressReport {
    pub operation_id: String,
    pub current: u64,
    pub total: u64,
    pub message: String,
    pub percentage: f64,
    pub timestamp: chrono::DateTime<chrono::Utc>,
}

impl ProgressReport {
    pub fn new(operation_id: String, current: u64, total: u64, message: String) -> Self {
        let percentage = if total > 0 {
            (current as f64 / total as f64) * 100.0
        } else {
            0.0
        };
        
        Self {
            operation_id,
            current,
            total,
            message,
            percentage,
            timestamp: chrono::Utc::now(),
        }
    }
}

/// 操作状态枚举
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum OperationStatus {
    Pending,
    InProgress,
    Completed,
    Failed,
    Cancelled,
}

/// 异步操作信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AsyncOperation {
    pub id: String,
    pub operation_type: String,
    pub status: OperationStatus,
    pub progress: Option<ProgressReport>,
    pub result: Option<serde_json::Value>,
    pub error: Option<String>,
    pub created_at: chrono::DateTime<chrono::Utc>,
    pub updated_at: chrono::DateTime<chrono::Utc>,
}

impl AsyncOperation {
    pub fn new(operation_type: String) -> Self {
        let now = chrono::Utc::now();
        Self {
            id: uuid::Uuid::new_v4().to_string(),
            operation_type,
            status: OperationStatus::Pending,
            progress: None,
            result: None,
            error: None,
            created_at: now,
            updated_at: now,
        }
    }
    
    pub fn update_progress(&mut self, progress: ProgressReport) {
        self.progress = Some(progress);
        self.status = OperationStatus::InProgress;
        self.updated_at = chrono::Utc::now();
    }
    
    pub fn complete(&mut self, result: serde_json::Value) {
        self.result = Some(result);
        self.status = OperationStatus::Completed;
        self.updated_at = chrono::Utc::now();
    }
    
    pub fn fail(&mut self, error: String) {
        self.error = Some(error);
        self.status = OperationStatus::Failed;
        self.updated_at = chrono::Utc::now();
    }
}
